package com.yanqu.road.server.gameplayer.module.monopolymarket;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.config.player.UserDecorationInfoResult;
import com.yanqu.road.entity.enums.eMessageSubscribeType;
import com.yanqu.road.entity.enums.eMonopolyMarketResType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.kuang.KuangConfig;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.monopolymarket.MonopolyMarketUserData;
import com.yanqu.road.entity.monopolymarket.config.MonopolyMarketResConfigData;
import com.yanqu.road.entity.monopolymarket.office.log.MonopolyMarketOfficeUserSeatLogData;
import com.yanqu.road.entity.monopolymarket.resgrab.MonopolyMarketReportData;
import com.yanqu.road.entity.monopolymarket.resgrab.MonopolyMarketResGrabDispatchInfo;
import com.yanqu.road.entity.monopolymarket.resgrab.MonopolyMarketResGrabMap;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.logic.bussiness.monopolymarket.MonopolyMarketBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.monopolymarket.MonopolyMarketProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.DecorationModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.MonopolyMarketCommonMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.kuang.KuangMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.manger.monopolymarket.MonopolyMarketMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description 榷场
 * @Author cwq
 * @Data 2021/8/11 16:54
 */
public class MonopolyMarketModule extends GeneralModule {


    public MonopolyMarketUserData baseData;

    /**
     * 资源争夺战 预扣除元宝数量
     */
    public int resGrabNeedConsumeGold;

    /**
     * 资源争夺战 预扣除体力
     */
    public int resGrabNeedPhysical;

    /**
     * 资源争夺战 预占领的等级
     */
    public int level;

    public List<MonopolyMarketReportData> officeReportList = new ArrayList<>();

    public List<MonopolyMarketReportData> resGrabReportList = new ArrayList<>();

    /**
     *  当前正在派遣的位置信息,结算完移除   k:系统类型， k:位置id v：派遣的对象集合
     */
    private Map<Integer, Map<Integer, Set<MonopolyMarketResGrabDispatchInfo>>> curDispatchInfoListMap = new ConcurrentHashMap<>();

    /**
     * 要塞派遣玩家信息 k:门客id v:要塞id
     */
    private Map<Integer,Integer> fortressDispatchMap = new ConcurrentHashMap<>();

    /**
     * 所在的系统id (0表示在大厅 1榷署 2王帐 3王宫)
     */
    public int inSystemId = -1;

    public MonopolyMarketModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        // 加载榷署战报
        if(MonopolyMarketMgr.group == null || !SystemOpenMgr.systemOpen(player, eSystemId.MonopolyMarket.getValue())) {
            return true;
        }
        baseData = MonopolyMarketMgr.getMonopolyMarketUserData(player.getUserId(),true);
        int officeReportTime = Math.max(MonopolyMarketMgr.group.getChangTime(),MonopolyMarketMgr.group.getOfficeCfgChangTime());

        officeReportList = MonopolyMarketBussiness.getMonopolyMarketReportDataList(player.getUserId(),eMonopolyMarketResType.OFFICE.getValue(),officeReportTime, GameConfig.MONOPOLYMARKET_KEEPINFO_1);
        // 加载资源点战报
        int kingReportTime = Math.max(MonopolyMarketMgr.group.getChangTime(),MonopolyMarketMgr.group.getKingCfgChangTime());
        List type2ReportList = MonopolyMarketBussiness.getMonopolyMarketReportDataList(player.getUserId(), eMonopolyMarketResType.RES_KING.getValue(),kingReportTime,GameConfig.MONOPOLYMARKET_KEEPINFO_2);

        int queenReportTime = Math.max(MonopolyMarketMgr.group.getChangTime(),MonopolyMarketMgr.group.getQueenCfgChangTime());
        List type3ReportList = MonopolyMarketBussiness.getMonopolyMarketReportDataList(player.getUserId(), eMonopolyMarketResType.RES_QUEEN.getValue(),queenReportTime,GameConfig.MONOPOLYMARKET_KEEPINFO_2);
        resGrabReportList.addAll(type2ReportList);
        resGrabReportList.addAll(type3ReportList);
        resGrabReportList.sort((t1,t2)-> Integer.compare(t1.getTime(), t2.getTime()));
        while (resGrabReportList.size() > 0 && resGrabReportList.size() > GameConfig.MONOPOLYMARKET_KEEPINFO_2){
            resGrabReportList.remove(0);
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if(baseData != null){
            if (baseData.isUpdateOption()) {
                MonopolyMarketBussiness.updateMonopolyMarketUserData(baseData);
            } else if (baseData.isInsertOption()) {
                MonopolyMarketBussiness.addMonopolyMarketUserData(baseData);
            }
        }
        // 更新榷署战报
        for(MonopolyMarketReportData reportData : officeReportList){
            if (reportData.isUpdateOption()) {
                MonopolyMarketBussiness.updateMonopolyMarketReportData(reportData);
            }else if(reportData.isInsertOption()) {
                MonopolyMarketBussiness.addMonopolyMarketReportData(reportData);
            }
        }

        for(MonopolyMarketReportData reportData : resGrabReportList){
            if (reportData.isUpdateOption()) {
                MonopolyMarketBussiness.updateMonopolyMarketReportData(reportData);
            }else if(reportData.isInsertOption()) {
                MonopolyMarketBussiness.addMonopolyMarketReportData(reportData);
            }
        }

        return true;
    }

    @Override
    public void afterLogin() {
        if(MonopolyMarketMgr.group == null || !MonopolyMarketMgr.canEnterSystem(player)){
            return;
        }
        getUserData();
        sendConfigToClient();
        // 设置微信推送时间
        try {
            MessageSubscribePushTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }

    public void initSystem(){
        baseData = MonopolyMarketMgr.getMonopolyMarketUserData(player.getUserId(),true);
        if(MonopolyMarketMgr.group == null || !MonopolyMarketMgr.canEnterSystem(player)){
            return;
        }
        synRoleData();
        sendConfigToClient();
    }


    /**
     * 收到分组信息的时候执行
     */
    public void initModule(){
        loadData();
        afterLogin();
    }

    /**
     * 设置推送时间
     */
    private void MessageSubscribePushTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        List<Long> timeList = new ArrayList<>();
        long weekStartTime = DateHelper.getThisWeekStartTime(GameConfig.DAY_SYSTEM_RESET_TIME) / 1000;
        weekStartTime = weekStartTime - (GameConfig.DAY_SYSTEM_RESET_TIME - 1) * DateHelper.DAY_SECONDS;
        timeList.add((ConfigMgr.getOfficeOpenSecondNew() + weekStartTime) * DateHelper.SECOND_MILLIONS);
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setSubTime(eMessageSubscribeType.MonopolyTime, timeList);
    }

    /**
     *  找跨服同步玩家 榷场数据
     */
    private void getUserData(){
        if (!MonopolyMarketMgr.canEnterSystem(player) || baseData == null) {
            return;
        }
        MonopolyMarketProto.MonopolyMarketCheckUserDataToCrossReqMsg.Builder req = MonopolyMarketProto.MonopolyMarketCheckUserDataToCrossReqMsg.newBuilder();
        req.setPlayerInfo(PlayerBasePb.parsePlayerBaseTempMsg(UserMgr.getUserBaseInfo(player.getUserId(), GameServer.getInstance().getServerId())));
        UserDecorationInfoResult result = player.getModule(DecorationModule.class).getCurMaxDecorationInfo();
        req.setDecorationClass(result.decorationClass);
        req.setDecorationOverTime((int)(result.decorationOverTime));
        player.sendPacket(CrossProtocol.C_CROSS_MONOPOLY_MARKET_GET_USER_DATA,req);
    }

    /**
     * 同步玩家数据
     */
    public void synRoleData(){
        MonopolyMarketProto.MonopolyMarketUserRespMsg.Builder builder = MonopolyMarketProto.MonopolyMarketUserRespMsg.newBuilder();
        // 下发玩家数据
        MonopolyMarketProto.MonopolyMarketUserEntity.Builder userEntity = MonopolyMarketMgr.builderMonopolyMarketUserEntity(this);
        builder.setUserData(userEntity);
        // 当前正在派遣的对象
        for(Map.Entry<Integer,Map<Integer,Set<MonopolyMarketResGrabDispatchInfo>>> item : curDispatchInfoListMap.entrySet()){
            int type = item.getKey();
            Map<Integer,Set<MonopolyMarketResGrabDispatchInfo>> map = item.getValue();
            for (Set<MonopolyMarketResGrabDispatchInfo> set : map.values()){
                for (MonopolyMarketResGrabDispatchInfo dispatchItem : set){
                    if(type == eMonopolyMarketResType.RES_KING.getValue()){
                        builder.addPatronsDispatchInfo(MonopolyMarketMgr.builderMonopolyMarketResGrabDispatchTimesEntity(dispatchItem));
                    }else if (type == eMonopolyMarketResType.RES_QUEEN.getValue()){
                        builder.addBeautyDispatchInfo(MonopolyMarketMgr.builderMonopolyMarketResGrabDispatchTimesEntity(dispatchItem));
                    }
                }
            }
        }
        // 要塞当前派遣的对象
        for (Map.Entry<Integer, Integer> item : fortressDispatchMap.entrySet()){
            builder.addFortressDispatchInfo(MonopolyMarketProto.MonopolyMarketFortressDispatchEntity.newBuilder().setPatronsId(item.getKey()).setFortressId(item.getValue()));
        }
        player.sendPacket(YanQuMessageUtils.buildMessage(ClientProtocol.U_MONOPOLY_MARKET_USER_DATA, builder));
    }

    /**
     * 同步玩家基本数据到跨服
     */
    public void syncPlayerBaseInfoToCross(){
        if (MonopolyMarketMgr.canEnterSystem(player)) {
            if(baseData.getOfficeCurPos() < 0){
                return;
            }
            MonopolyMarketProto.MonopolyMarketSynUserDataToCrossReqMsg.Builder builder = MonopolyMarketProto.MonopolyMarketSynUserDataToCrossReqMsg.newBuilder();
            UserInfo userInfo = UserMgr.getUserInfo(player.getUserId());
            if(userInfo.getDecoration() != null){
                builder.setDecoration(userInfo.getDecoration());
            }
            builder.setTitleId(userInfo.getTitleId());
            builder.setPrestige(userInfo.getPrestige().longValue());
            builder.setCurPos(baseData.getOfficeCurPos());
            UserDecorationInfoResult result = player.getModule(DecorationModule.class).getCurMaxDecorationInfo();
            builder.setDecorationClass(result.decorationClass);
            builder.setDecorationOverTime((int)(result.decorationOverTime));
            player.sendPacket(YanQuMessageUtils.buildMessage(CrossProtocol.C_CROSS_MONOPOLY_MARKET_SYN_USER_DATA_TO_CROSS, builder));
        }
    }

    /**
     * 发送配置
     */
    public void sendConfigToClient() {
        MonopolyMarketProto.MonopolyMarketConfigRespMsg.Builder config = MonopolyMarketProto.MonopolyMarketConfigRespMsg.newBuilder();
        if (MonopolyMarketMgr.canEnterSystem(player)) {
            // 分组配置
            MonopolyMarketProto.MonopolyMarketServerGroupEntity.Builder serverGroupEntity = MonopolyMarketProto.MonopolyMarketServerGroupEntity.newBuilder();
            if(MonopolyMarketMgr.group != null){
                serverGroupEntity.setGroupId(MonopolyMarketMgr.group.getGroupId());
                serverGroupEntity.addAllServerList(MonopolyMarketMgr.group.getServerList());
                serverGroupEntity.setFortressState(MonopolyMarketMgr.group.getFortressState());
                serverGroupEntity.setGroupTime(MonopolyMarketMgr.group.getChangTime());
                config.setServerGroupEntity(serverGroupEntity);

                JSONObject jsonObject = JSONObject.parseObject(MonopolyMarketMgr.backEndConfig.getResConfig());
                for(MonopolyMarketResConfigData item : MonopolyMarketMgr.resConfigMap.values()) {
                    MonopolyMarketProto.MonopolyMarketResConfigEntity.Builder resConfigBuilder = MonopolyMarketMgr.builderMonopolyMarketResConfigEntity(item);
                    String extendParam = jsonObject.getString(String.valueOf(item.getId()));
                    if (extendParam != null) {
                        resConfigBuilder.setExtendParam(extendParam);
                        String str = MonopolyMarketCommonMgr.getNpcStr(MonopolyMarketMgr.group.getServerList(), MonopolyMarketMgr.backEndConfig, item);
                        resConfigBuilder.setNpcList(str);
                    }
                    config.addResEntityList(resConfigBuilder);
                }
            }
            // 下发地图
            for(MonopolyMarketResGrabMap item : MonopolyMarketMgr.resGrabMapMap.values()){
                MonopolyMarketProto.MonopolyMarketResGrabMapEntity.Builder mapBuilder = MonopolyMarketProto.MonopolyMarketResGrabMapEntity.newBuilder();
                mapBuilder.setSide(item.side);
                mapBuilder.setType(item.type);
                mapBuilder.addAllLevel(item.indexLevelList);
                config.addRedGrabMaps(mapBuilder);
            }
        }
        player.sendPacket(ClientProtocol.U_MONOPOLY_MARKET_SYN_CONFIG, config);
    }

    public Map<Integer, Set<MonopolyMarketResGrabDispatchInfo>> getCurDispatchInfoListMap(int type, boolean newIfNull){
        Map<Integer, Set<MonopolyMarketResGrabDispatchInfo>> map = curDispatchInfoListMap.get(type);
        if(map == null && newIfNull){
            map = new ConcurrentHashMap<>();
            curDispatchInfoListMap.put(type,map);
        }
        return map;
    }


    public Map<Integer, Map<Integer, Set<MonopolyMarketResGrabDispatchInfo>>> getCurDispatchInfoListMap() {
        return curDispatchInfoListMap;
    }

    /**
     * 清空榷署战报
     */
    public void clearOfficeReport(){
        synchronized (officeReportList){
            officeReportList.clear();
        }
    }

    /**
     * 检查玩家数据  该操作应该在玩家登陆后，跨服同步完数据后
     *
     * 有一种特殊情况 ： 玩家入座之后 位置没被抢 改了分组或者改了配置  一直不上线  途中改了n轮的分组和配置  无法 确定离开位置的时间，就取 最接近的时间
     *
     */
    public void checkUserData(){
        if(MonopolyMarketMgr.group == null){
            return;
        }
        if(baseData == null || baseData.getOfficeSeatTime() <= 0){
            return;
        }
        int refreshTime = 0;
        if(baseData.getOfficeSeatTime() < MonopolyMarketMgr.group.getChangTime()){
            refreshTime = MonopolyMarketMgr.group.getChangTime();
        }
        if(baseData.getOfficeSeatTime() < MonopolyMarketMgr.group.getOfficeCfgChangTime()){
            if(refreshTime == 0 || MonopolyMarketMgr.group.getOfficeCfgChangTime() < refreshTime){
                refreshTime = MonopolyMarketMgr.group.getOfficeCfgChangTime();
            }
        }
        refreshTime = Math.min(refreshTime,MonopolyMarketMgr.exitOfficeTime(this));
        if(refreshTime > 0){
            MonopolyMarketMgr.refreshOfficeTeaReward(this,refreshTime);
            MonopolyMarketMgr.refreshPhysical(this,refreshTime,true);

            LogMgr.addMonopolyMarketOfficeUserSeatLogData(new MonopolyMarketOfficeUserSeatLogData(this.getUserId(),this.baseData.getOfficeCurPos(),this.baseData.getOfficeLevel(),this.baseData.getOfficeNo(),0,this.baseData.getPhysical(),this.baseData.getOfficeSeatTime(), DateHelper.getCurrentSecond()));

            MonopolyMarketMgr.resetOfficeSeat(this);
            baseData.setOfficeRobTimes(0);
        }
    }

    /**
     * 判断对象是否被派遣
     * @return
     */
    public boolean isDispatch(int type,int objectId){
        Map<Integer, Set<MonopolyMarketResGrabDispatchInfo>>  map = getCurDispatchInfoListMap(type,false);
        if(map == null){
            return false;
        }
        for (Set<MonopolyMarketResGrabDispatchInfo> item : map.values()){
            for (MonopolyMarketResGrabDispatchInfo dispatchInfo : item){
                if(dispatchInfo.getDispatchId() == objectId){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 添加派遣记录
     * @param type
     * @param posIndex
     */
    public void addDispatchInfo(int type,int posIndex, List<Integer> dispatchList,int time){
        Map<Integer, Set<MonopolyMarketResGrabDispatchInfo>>  map = getCurDispatchInfoListMap(type,true);

        Set<MonopolyMarketResGrabDispatchInfo> set = map.get(posIndex);
        if(set == null){
            set = new HashSet<>();
            map.put(posIndex,set);
        }
        for (int objectId : dispatchList){
            MonopolyMarketResGrabDispatchInfo dispatchInfo = new MonopolyMarketResGrabDispatchInfo();
            dispatchInfo.setDispatchId(objectId);
            dispatchInfo.setPosIndex(posIndex);
            dispatchInfo.setType(type);
            dispatchInfo.setSeatTime(time);
            set.add(dispatchInfo);
        }
    }

    /**
     * 获取包含该派遣id的派遣据点
     * @param type
     * @param dispatchIdSet
     * @return
     */
    public Set<Integer> getCurDispatchInfo(int type , Set<Integer> dispatchIdSet){
        Set<Integer> set = new HashSet<>();
        Map<Integer, Set<MonopolyMarketResGrabDispatchInfo>>  map = getCurDispatchInfoListMap(type,false);
        if(map != null){
            for (Integer dispatchId : dispatchIdSet){
                for (Set<MonopolyMarketResGrabDispatchInfo> item : map.values()){
                    for (MonopolyMarketResGrabDispatchInfo dispatchInfo : item){
                        if(dispatchInfo.getDispatchId() == dispatchId){
                            set.add(dispatchInfo.getPosIndex());
                            break;
                        }
                    }
                }
            }
        }
        return set;
    }

    public Map<Integer, Integer> getFortressDispatchMap() {
        return fortressDispatchMap;
    }


    /**
     * 同步要塞派遣信息
     * @param list
     */
    public void synFortressDispatchInfo(List<MonopolyMarketProto.MonopolyMarketFortressDispatchEntity> list){
        getFortressDispatchMap().clear();
        for(MonopolyMarketProto.MonopolyMarketFortressDispatchEntity item : list){
            getFortressDispatchMap().put(item.getPatronsId(),item.getFortressId());
        }
    }

}
